Have xenstored initialise its connections, meaning that xend can be out of
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Mon, 17 Oct 2005 15:22:05 +0000 (16:22 +0100)
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Mon, 17 Oct 2005 15:22:05 +0000 (16:22 +0100)
that loop completely -- the xc_init_store, initDomainStore calls can all go.

Have xenstored understand where the local domain information goes.  Xend no
longer has to generate a path and pass it to xenstored through
xs_introduce_domain -- we just allow xenstored to generate the path, and then
call GetDomainPath later.  There is still some work required to tidy this up.

Change the uuid module to generate uuids as lists of bytes, not in the
stringified form.  Added a unit test for that module.

Change the semantics of Xend restart, relying on these changes to the
xenstored semantics and earlier changes to add an opaque handle to the
hypervisor's domain-specific data block.  The semantics are now clearer, as
Xend can validate whether the details in the store match the current live
domain.

Added a usage statement to xenstored.

Some of this code is by Steven Hand.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
17 files changed:
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h
tools/libxc/xc_misc.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/lowlevel/xs/xs.c
tools/python/xen/xend/XendCheckpoint.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/uuid.py
tools/python/xen/xend/xenstore/xsutil.py
tools/xenstore/xenstored_core.c
tools/xenstore/xenstored_domain.c
tools/xenstore/xs.c
tools/xenstore/xs.h

index 6ed338bab10e48d3da2f35768733b313039cd9cd..b13f22a771594c59708aa44dffc3896244c64127 100644 (file)
@@ -25,8 +25,6 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
-#include <asm-xen/xen-public/xen.h>
-#include <asm/hypervisor.h>
 #include <asm-xen/linux-public/privcmd.h>
 #include <asm/hypervisor.h>
 #include <asm-xen/xen-public/xen.h>
@@ -219,41 +217,6 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
        }
        break;
 
-       case IOCTL_PRIVCMD_INITDOMAIN_STORE: {
-               extern int do_xenbus_probe(void*);
-               unsigned long page;
-
-               if (xen_start_info->store_evtchn != 0) {
-                       ret = xen_start_info->store_mfn;
-                       break;
-               }
-
-               /* Allocate page. */
-               page = get_zeroed_page(GFP_KERNEL);
-               if (!page) {
-                       ret = -ENOMEM;
-                       break;
-               }
-
-               /* We don't refcnt properly, so set reserved on page.
-                * (this allocation is permanent) */
-               SetPageReserved(virt_to_page(page));
-
-               /* Initial connect. Setup channel and page. */
-               xen_start_info->store_evtchn = data;
-               xen_start_info->store_mfn =
-                       pfn_to_mfn(virt_to_phys((void *)page) >>
-                                  PAGE_SHIFT);
-               ret = xen_start_info->store_mfn;
-
-               /* 
-               ** Complete initialization of xenbus (viz. set up the 
-               ** connection to xenstored now that it has started). 
-               */
-               kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
-       }
-       break;
-
        default:
                ret = -EINVAL;
                break;
index e3863a2c79805ab5966f91b8d0142ae860678a60..a1e83f780085dd36d197863c73a24699d6260b9a 100644 (file)
 #include <asm-xen/xenbus.h>
 #include "xenbus_comms.h"
 
-static int xenbus_irq;
+static int xenbus_irq      = 0;
+
+extern void xenbus_probe(void *); 
+extern int xenstored_ready; 
+static DECLARE_WORK(probe_work, xenbus_probe, NULL);
 
 DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
 
@@ -47,6 +51,11 @@ static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
 
 static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
 {
+       if(unlikely(xenstored_ready == 0)) {
+               xenstored_ready = 1; 
+               schedule_work(&probe_work); 
+       } 
+
        wake_up(&xb_waitq);
        return IRQ_HANDLED;
 }
@@ -169,10 +178,6 @@ int xb_init_comms(void)
 
        if (xenbus_irq)
                unbind_evtchn_from_irqhandler(xenbus_irq, &xb_waitq);
-       xenbus_irq = 0;
-
-       if (!xen_start_info->store_evtchn)
-               return 0;
 
        err = bind_evtchn_to_irqhandler(
                xen_start_info->store_evtchn, wake_waiting,
index e04798a5623ce61e081d5e20bfd5ed543e8f92fc..e5c9de11397f1c368f9c11ba5cd1c89ea0732a76 100644 (file)
  */
 #define DEBUG
 
-#include <asm/hypervisor.h>
-#include <asm-xen/xenbus.h>
-#include <asm-xen/balloon.h>
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/fcntl.h>
-#include <stdarg.h>
+#include <linux/mm.h>
 #include <linux/notifier.h>
+#include <linux/kthread.h>
+
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/hypervisor.h>
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xen_proc.h>
+#include <asm-xen/balloon.h>
+#include <asm-xen/evtchn.h>
+#include <asm-xen/linux-public/evtchn.h>
+
 #include "xenbus_comms.h"
 
 extern struct semaphore xenwatch_mutex;
@@ -634,15 +643,19 @@ void xenbus_resume(void)
        bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
 }
 
+
+/* A flag to determine if xenstored is 'ready' (i.e. has started) */
+int xenstored_ready = 0; 
+
+
 int register_xenstore_notifier(struct notifier_block *nb)
 {
        int ret = 0;
 
-       if (xen_start_info->store_evtchn) {
+        if(xenstored_ready > 0) 
                ret = nb->notifier_call(nb, 0, NULL);
-       } else {
+       else 
                notifier_chain_register(&xenstore_chain, nb);
-       }
 
        return ret;
 }
@@ -654,22 +667,11 @@ void unregister_xenstore_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(unregister_xenstore_notifier);
 
-/* 
-** Called either from below xenbus_probe_init() initcall (for domUs) 
-** or, for dom0, from a thread created in privcmd/privcmd.c (after 
-** the user-space tools have invoked initDomainStore()) 
-*/
-int do_xenbus_probe(void *unused)
-{
-       int err = 0;
 
-       /* Initialize the interface to xenstore. */
-       err = xs_init();
-       if (err) {
-               printk("XENBUS: Error initializing xenstore comms:"
-                      " %i\n", err);
-               return err;
-       }
+
+void xenbus_probe(void *unused)
+{
+       BUG_ON((xenstored_ready <= 0)); 
 
        /* Enumerate devices in xenstore. */
        xenbus_probe_devices(&xenbus_frontend);
@@ -682,27 +684,101 @@ int do_xenbus_probe(void *unused)
        /* Notify others that xenstore is up */
        notifier_call_chain(&xenstore_chain, 0, 0);
 
-       return 0;
+       return;
+}
+
+
+static struct proc_dir_entry *xsd_mfn_intf;
+static struct proc_dir_entry *xsd_port_intf;
+
+
+static int xsd_mfn_read(char *page, char **start, off_t off,
+                        int count, int *eof, void *data)
+{
+       int len; 
+       len  = sprintf(page, "%ld", xen_start_info->store_mfn); 
+       *eof = 1; 
+       return len; 
 }
 
+static int xsd_port_read(char *page, char **start, off_t off,
+                        int count, int *eof, void *data)
+{
+       int len; 
+
+       len  = sprintf(page, "%d", xen_start_info->store_evtchn); 
+       *eof = 1; 
+       return len; 
+}
+
+
 static int __init xenbus_probe_init(void)
 {
-       if (xen_init() < 0)
+       int err = 0;
+       /* 
+       ** Domain0 doesn't have a store_evtchn or store_mfn yet. 
+       */
+       int dom0 = (xen_start_info->store_evtchn == 0);
+
+       printk("xenbus_probe_init\n");
+
+       if (xen_init() < 0) {
+               printk("xen_init failed\n");
                return -ENODEV;
+       }
 
+       /* Register ourselves with the kernel bus & device subsystems */
        bus_register(&xenbus_frontend.bus);
        bus_register(&xenbus_backend.bus);
        device_register(&xenbus_frontend.dev);
        device_register(&xenbus_backend.dev);
 
-       /* 
-       ** Domain0 doesn't have a store_evtchn yet - this will
-       ** be set up later by xend invoking initDomainStore() 
-       */
-       if (!xen_start_info->store_evtchn)
-               return 0;
+       if (dom0) {
+
+               unsigned long page;
+               evtchn_op_t op = { 0 };
+
+
+               /* Allocate page. */
+               page = get_zeroed_page(GFP_KERNEL);
+               if (!page) 
+                       return -ENOMEM; 
+
+               /* We don't refcnt properly, so set reserved on page.
+                * (this allocation is permanent) */
+               SetPageReserved(virt_to_page(page));
+
+               xen_start_info->store_mfn =
+                       pfn_to_mfn(virt_to_phys((void *)page) >>
+                                  PAGE_SHIFT);
+               
+               /* Next allocate a local port which xenstored can bind to */
+               op.cmd = EVTCHNOP_alloc_unbound;
+               op.u.alloc_unbound.dom        = DOMID_SELF;
+               op.u.alloc_unbound.remote_dom = 0; 
+
+               BUG_ON(HYPERVISOR_event_channel_op(&op)); 
+               xen_start_info->store_evtchn = op.u.alloc_unbound.port;
+
+               /* And finally publish the above info in /proc/xen */
+               if((xsd_mfn_intf = create_xen_proc_entry("xsd_mfn", 0400)))
+                       xsd_mfn_intf->read_proc = xsd_mfn_read; 
+               if((xsd_port_intf = create_xen_proc_entry("xsd_port", 0400)))
+                       xsd_port_intf->read_proc = xsd_port_read;
+       }
+
+       /* Initialize the interface to xenstore. */
+       err = xs_init(); 
+       if (err) {
+               printk("XENBUS: Error initializing xenstore comms: %i\n", err);
+               return err; 
+       }
+
+       if (!dom0) {
+               xenstored_ready = 1;
+               xenbus_probe(NULL);
+       }
 
-       do_xenbus_probe(NULL);
        return 0;
 }
 
index 1246dbd64bd835a3bdba713f10a62b49d035a319..292ade02b8b6cb123e60e5c02216120e7b4285ea 100644 (file)
@@ -76,8 +76,6 @@ typedef struct privcmd_blkmsg
        _IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
 #define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN                  \
        _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
-#define IOCTL_PRIVCMD_INITDOMAIN_STORE                         \
-       _IOC(_IOC_READ, 'P', 5, 0)
 
 #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
 
index ab263689c5ecf3cfdb2c2893b442e6802cde2678..b0987d2a4733e384f213948284a40b72084929c3 100644 (file)
@@ -131,11 +131,6 @@ int xc_msr_write(int xc_handle, int cpu_mask, int msr, unsigned int low,
     return rc;
 }
 
-long xc_init_store(int xc_handle, int remote_port)
-{
-    return ioctl(xc_handle, IOCTL_PRIVCMD_INITDOMAIN_STORE, remote_port);
-}
-
 /*
  * Local variables:
  * mode: C
index 818a29df243e5964ebf97786879f432a66f1767d..98408f25bf8cb75181c3b00fc177b2b0e42dd8e2 100644 (file)
@@ -236,12 +236,12 @@ int xc_domain_getinfolist(int xc_handle,
                           xc_domaininfo_t *info);
 
 /**
- * This function returns information about one domain.  This information is
- * more detailed than the information from xc_domain_getinfo().
+ * This function returns information about the execution context of a
+ * particular vcpu of a domain.
  *
  * @parm xc_handle a handle to an open hypervisor interface
  * @parm domid the domain to get information from
- * @parm info a pointer to an xc_domaininfo_t to store the domain information
+ * @parm vcpu the vcpu number
  * @parm ctxt a pointer to a structure to store the execution context of the
  *            domain
  * @return 0 on success, -1 on failure
@@ -489,15 +489,6 @@ int xc_dom0_op(int xc_handle, dom0_op_t *op);
 
 int xc_version(int xc_handle, int cmd, void *arg);
 
-/* Initializes the store (for dom0)
-   remote_port should be the remote end of a bound interdomain channel between
-   the store and dom0.
-
-   This function returns a shared frame that should be passed to
-   xs_introduce_domain
- */
-long xc_init_store(int xc_handle, int remote_port);
-
 /*
  * MMU updates.
  */
index 4a11ef77c50f5cfe38e0a69051c52735e6a8330a..927b1ccdc590eb1724d3dd46faf81b5d98f23d5a 100644 (file)
@@ -862,23 +862,6 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
     return zero;
 }
 
-static PyObject *pyxc_init_store(PyObject *self, PyObject *args,
-                                PyObject *kwds)
-{
-    XcObject *xc = (XcObject *)self;
-
-    int remote_port;
-
-    static char *kwd_list[] = { "remote_port", NULL };
-
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, 
-                                      &remote_port) )
-        return NULL;
-
-    return PyInt_FromLong(xc_init_store(xc->xc_handle, remote_port));
-}
-
-
 static PyMethodDef pyxc_methods[] = {
     { "handle",
       (PyCFunction)pyxc_handle,
@@ -1158,13 +1141,6 @@ static PyMethodDef pyxc_methods[] = {
       " mem_kb [long]: .\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
-    { "init_store", 
-      (PyCFunction)pyxc_init_store, 
-      METH_VARARGS | METH_KEYWORDS, "\n"
-      "Initialize the store event channel and return the store page mfn.\n"
-      " remote_port [int]: store event channel port number.\n"
-      "Returns: [int] mfn on success; <0 on error.\n" },
-
     { NULL, NULL, 0, NULL }
 };
 
index b6764192275168c35a93d0c08f71220d67cbd4a2..b5ce2c357bead9dccd4398c4f328022add4ea5d7 100644 (file)
@@ -686,7 +686,6 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
        " dom  [int]   : domain id\n"                                   \
        " page [long]  : address of domain's xenstore page\n"           \
        " port [int]   : port the domain is using for xenstore\n"       \
-       " path [string]: path to the domain's data in xenstore\n"       \
        "\n"                                                            \
        "Returns None on success.\n"                                    \
        "Raises RuntimeError on error.\n"                               \
@@ -695,12 +694,11 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
 static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
                                        PyObject *kwds)
 {
-    static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
-    static char *arg_spec = "iiis|";
+    static char *kwd_spec[] = { "dom", "page", "port", NULL };
+    static char *arg_spec = "iii";
     domid_t dom = 0;
     unsigned long page = 0;
     unsigned int port = 0;
-    char *path = NULL;
 
     struct xs_handle *xh = xshandle(self);
     PyObject *val = NULL;
@@ -709,10 +707,10 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
     if (!xh)
         goto exit;
     if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
-                                     &dom, &page, &port, &path))
+                                     &dom, &page, &port))
         goto exit;
     Py_BEGIN_ALLOW_THREADS
-    xsval = xs_introduce_domain(xh, dom, page, port, path);
+    xsval = xs_introduce_domain(xh, dom, page, port);
     Py_END_ALLOW_THREADS
     if (!xsval) {
         PyErr_SetFromErrno(PyExc_RuntimeError);
index d8ae85b91ebfb60717496e677d1cfcdc708eb311..25c496add0adbb78b8d3b1abae8f092f2dd4819e 100644 (file)
@@ -143,15 +143,13 @@ def restore(xd, fd):
             if m:
                 store_mfn = int(m.group(2))
                 dominfo.setStoreRef(store_mfn)
-                log.debug("IntroduceDomain %d %d %d %s",
+                log.debug("IntroduceDomain %d %d %d",
                           dominfo.getDomid(),
                           store_mfn,
-                          dominfo.store_channel,
-                          dominfo.getDomainPath())
+                          dominfo.store_channel)
                 IntroduceDomain(dominfo.getDomid(),
                                 store_mfn,
-                                dominfo.store_channel,
-                                dominfo.getDomainPath())
+                                dominfo.store_channel)
             else:
                 m = re.match(r"^(console-mfn) (\d+)$", line)
                 if m:
@@ -171,6 +169,7 @@ def forkHelper(cmd, fd, inputHandler, closeToChild):
     if closeToChild:
         child.tochild.close()
 
+    lasterr = "error unknown"
     try:
         fds = [child.fromchild.fileno(),
                child.childerr.fileno()]
index 6f1ab9b84e2b596b84a8e2e2714fd6f82e70f8dd..802c53f689179485c84eb8a7952959ee1f8b8706 100644 (file)
  Nothing here is persistent (across reboots).
  Needs to be persistent for one uptime.
 """
-import os
+
 import logging
+import os
+import sys
 import threading
 
 import xen.lowlevel.xc
@@ -62,8 +64,11 @@ class XendDomain:
 
         self.domains_lock.acquire()
         try:
-            self.refresh(True)
+            self._add_domain(
+                XendDomainInfo.recreate(self.xen_domains()[PRIV_DOMAIN],
+                                        True))
             self.dom0_setup()
+            self.refresh(True)
         finally:
             self.domains_lock.release()
 
@@ -178,25 +183,23 @@ class XendDomain:
                             'Cannot recreate information for dying domain %d.'
                             '  Xend will ignore this domain from now on.',
                             doms[d]['dom'])
+                elif d == PRIV_DOMAIN:
+                    log.fatal(
+                        "No record of privileged domain %d!  Terminating.", d)
+                    sys.exit(1)
                 else:
                     try:
-                        dominfo = XendDomainInfo.recreate(doms[d])
-                        self._add_domain(dominfo)
+                        self._add_domain(
+                            XendDomainInfo.recreate(doms[d], False))
                     except:
-                        if d == PRIV_DOMAIN:
-                            log.exception(
-                                "Failed to recreate information for domain "
-                                "%d.  Doing nothing except crossing my "
-                                "fingers.", d)
-                        else:
-                            log.exception(
-                                "Failed to recreate information for domain "
-                                "%d.  Destroying it in the hope of "
-                                "recovery.", d)
-                            try:
-                                xc.domain_destroy(dom = d)
-                            except:
-                                log.exception('Destruction of %d failed.', d)
+                        log.exception(
+                            "Failed to recreate information for domain "
+                            "%d.  Destroying it in the hope of "
+                            "recovery.", d)
+                        try:
+                            xc.domain_destroy(dom = d)
+                        except:
+                            log.exception('Destruction of %d failed.', d)
 
 
     ## public:
index 79fdd38a9ada176834fde3806af4cc9ee2329125..0ad6f5a7dd627617418c4a5e101e596f76b07fe2 100644 (file)
@@ -28,7 +28,6 @@ import logging
 import string
 import time
 import threading
-import errno
 
 import xen.lowlevel.xc
 from xen.util import asserts
@@ -42,7 +41,7 @@ from xen.xend.XendBootloader import bootloader
 from xen.xend.XendError import XendError, VmError
 from xen.xend.XendRoot import get_component
 
-from uuid import getUuid
+import uuid
 
 from xen.xend.xenstore.xstransact import xstransact
 from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
@@ -153,7 +152,7 @@ def create(config):
 
     log.debug("XendDomainInfo.create(%s)", config)
 
-    vm = XendDomainInfo(getUuid(), parseConfig(config))
+    vm = XendDomainInfo(uuid.create(), parseConfig(config))
     try:
         vm.construct()
         vm.initDomain()
@@ -169,7 +168,7 @@ def create(config):
         raise
 
 
-def recreate(xeninfo):
+def recreate(xeninfo, priv):
     """Create the VM object for an existing domain.  The domain must not
     be dying, as the paths in the store should already have been removed,
     and asking us to recreate them causes problems."""
@@ -179,39 +178,52 @@ def recreate(xeninfo):
     assert not xeninfo['dying']
 
     domid = xeninfo['dom']
+    dompath = GetDomainPath(domid)
+    if not dompath:
+        raise XendError(
+            'No domain path in store for existing domain %d' % domid)
     try:
-        dompath = GetDomainPath(domid)
-        if not dompath:
-            raise XendError(
-                'No domain path in store for existing domain %d' % domid)
         vmpath = xstransact.Read(dompath, "vm")
         if not vmpath:
             raise XendError(
                 'No vm path in store for existing domain %d' % domid)
-        uuid = xstransact.Read(vmpath, "uuid")
-        if not uuid:
+        uuid1_str = xstransact.Read(vmpath, "uuid")
+        if not uuid1_str:
             raise XendError(
                 'No vm/uuid path in store for existing domain %d' % domid)
 
-        log.info("Recreating domain %d, UUID %s.", domid, uuid)
+        uuid1 = uuid.fromString(uuid1_str)
+
+        uuid2 = xeninfo['handle']
+
+        if uuid1 != uuid2:
+            raise XendError(
+                'Uuid in store does not match uuid for existing domain %d: '
+                '%s != %s' % (domid, uuid1_str, uuid.toString(uuid2)))
+
+        log.info("Recreating domain %d, UUID %s.", domid, uuid1_str)
 
-        vm = XendDomainInfo(uuid, xeninfo, domid, True)
+        vm = XendDomainInfo(uuid2, xeninfo, domid, dompath, True)
 
     except Exception, exn:
         log.warn(str(exn))
 
-        uuid = getUuid()
+        if priv:
+            new_uuid = [0 for i in range(0, 16)]
+        else:
+            new_uuid = uuid.create()
 
-        log.info("Recreating domain %d with new UUID %s.", domid, uuid)
+        log.info("Recreating domain %d with new UUID %s.", domid,
+                 uuid.toString(new_uuid))
 
-        vm = XendDomainInfo(uuid, xeninfo, domid, True)
+        vm = XendDomainInfo(new_uuid, xeninfo, domid, dompath, True)
         vm.removeDom()
         vm.storeVmDetails()
         vm.storeDomDetails()
 
-    vm.create_channel()
-    if domid == 0:
-        vm.initStoreConnection()
+    if domid != 0:
+        # Setup store and console channels 
+        vm.create_channels()
 
     vm.refreshShutdown(xeninfo)
     return vm
@@ -225,12 +237,12 @@ def restore(config):
 
     log.debug("XendDomainInfo.restore(%s)", config)
 
-    uuid = sxp.child_value(config, 'uuid')
-    vm = XendDomainInfo(uuid, parseConfig(config))
+    vm = XendDomainInfo(uuid.fromString(sxp.child_value(config, 'uuid')),
+                        parseConfig(config))
     try:
         vm.construct()
         vm.configure()
-        vm.create_channel()
+        vm.create_channels()
         vm.storeVmDetails()
         vm.storeDomDetails()
         vm.refreshShutdown()
@@ -355,9 +367,10 @@ class XendDomainInfo:
     MINIMUM_RESTART_TIME = 20
 
 
-    def __init__(self, uuid, info, domid = None, augment = False):
+    def __init__(self, uuidbytes, info, domid = None, dompath = None,
+                 augment = False):
 
-        self.uuid = uuid
+        self.uuidbytes = uuidbytes
         self.info = info
 
         if domid is not None:
@@ -367,11 +380,8 @@ class XendDomainInfo:
         else:
             self.domid = None
 
-        self.vmpath  = VMROOT + uuid
-        if self.domid is None:
-            self.dompath = None
-        else:
-            self.dompath = DOMROOT + str(self.domid)
+        self.vmpath  = VMROOT + uuid.toString(uuidbytes)
+        self.dompath = dompath
 
         if augment:
             self.augmentInfo()
@@ -440,6 +450,9 @@ class XendDomainInfo:
             defaultInfo('cpu',          lambda: None)
             defaultInfo('cpu_weight',   lambda: 1.0)
             defaultInfo('vcpus',        lambda: 1)
+
+            self.info['vcpus'] = int(self.info['vcpus'])
+
             defaultInfo('vcpu_avail',   lambda: (1 << self.info['vcpus']) - 1)
             defaultInfo('bootloader',   lambda: None)
             defaultInfo('backend',      lambda: [])
@@ -576,7 +589,7 @@ class XendDomainInfo:
 
     def storeVmDetails(self):
         to_store = {
-            'uuid':               self.uuid,
+            'uuid':               uuid.toString(self.uuidbytes),
 
             # XXX
             'memory/target':      str(self.info['memory_KiB'])
@@ -651,9 +664,6 @@ class XendDomainInfo:
     def getDomainPath(self):
         return self.dompath
 
-    def getUuid(self):
-        return self.uuid
-
 
     def getVCpuCount(self):
         return self.info['vcpus']
@@ -921,7 +931,7 @@ class XendDomainInfo:
     def sxpr(self):
         sxpr = ['domain',
                 ['domid',   self.domid],
-                ['uuid',    self.uuid],
+                ['uuid',    uuid.toString(self.uuidbytes)],
                 ['memory',  self.info['memory_KiB'] / 1024]]
 
         for e in ROUNDTRIPPING_CONFIG_ENTRIES:
@@ -1038,7 +1048,8 @@ class XendDomainInfo:
                   self.domid,
                   self.info['ssidref'])
 
-        self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'])
+        self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'],
+                                      handle = self.uuidbytes)
 
         if self.domid < 0:
             raise VmError('Creating domain failed: name=%s' %
@@ -1089,10 +1100,9 @@ class XendDomainInfo:
     def construct_image(self):
         """Construct the boot image for the domain.
         """
-        self.create_channel()
+        self.create_channels()
         self.image.createImage()
-        IntroduceDomain(self.domid, self.store_mfn,
-                        self.store_channel, self.dompath)
+        IntroduceDomain(self.domid, self.store_mfn, self.store_channel)
 
 
     ## public:
@@ -1199,7 +1209,7 @@ class XendDomainInfo:
         self.storeDom(path, port)
         return port
 
-    def create_channel(self):
+    def create_channels(self):
         """Create the channels to the domain.
         """
         self.store_channel = self.eventChannel("store/port")
@@ -1312,13 +1322,15 @@ class XendDomainInfo:
         """
         
         new_name = self.generateUniqueName()
-        new_uuid = getUuid()
+        new_uuid = uuid.create()
+        new_uuid_str = uuid.toString(new_uuid)
         log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
-                 self.info['name'], self.domid, self.uuid, new_name, new_uuid)
+                 self.info['name'], self.domid, uuid.toString(self.uuidbytes),
+                 new_name, new_uuid_str)
         self.release_devices()
         self.info['name'] = new_name
-        self.uuid = new_uuid
-        self.vmpath = VMROOT + new_uuid
+        self.uuidbytes = new_uuid
+        self.vmpath = VMROOT + new_uuid_str
         self.storeVmDetails()
         self.preserve()
 
@@ -1384,20 +1396,6 @@ class XendDomainInfo:
         self.storeDom("control/sysrq", '%c' % key)
 
 
-    def initStoreConnection(self):
-        ref = xc.init_store(self.store_channel)
-        if ref and ref >= 0:
-            self.setStoreRef(ref)
-            try:
-                IntroduceDomain(self.domid, ref, self.store_channel,
-                                self.dompath)
-            except RuntimeError, ex:
-                if ex.args[0] == errno.EISCONN:
-                    pass
-                else:
-                    raise
-
-
     def infoIsSet(self, name):
         return name in self.info and self.info[name] is not None
 
index b37cb17a39523f4b30ac692e0e67c9557dc2c327..77517e9fbeac2af10ae9662b09714528b884ae9b 100644 (file)
@@ -36,23 +36,27 @@ def getUuidUuidgen(random = True):
         cmd += " -r"
     else:
         cmd += " -t"
-    return commands.getoutput(cmd)
+    return fromString(commands.getoutput(cmd))
 
 
 def getUuidRandom():
     """Generate a random UUID."""
     
-    bytes = [ random.randint(0, 255) for i in range(0, 16) ]
-    # Encode the variant.
-    bytes[6] = (bytes[6] & 0x0f) | 0x40
-    bytes[8] = (bytes[8] & 0x3f) | 0x80
-    f = "%02x"
-    return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(bytes) )
+    return [ random.randint(0, 255) for i in range(0, 16) ]
 
 
 #uuidFactory = getUuidUuidgen
 uuidFactory = getUuidRandom
 
 
-def getUuid():
+def create():
     return uuidFactory()
+
+
+def toString(u):
+    f = "%02x"
+    return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(u) )
+
+def fromString(s):
+    s = s.replace('-', '')
+    return [ int(s[i : i + 2], 16) for i in range(0, 32, 2) ]
index 486a3eeb4da04bfeeacea80e1e1ced0e128f2103..d2af3c5ac5498fd99ce640d8162e4db945c4294a 100644 (file)
@@ -19,8 +19,8 @@ def xshandle():
         xs_lock.release()
     return xs_handle
 
-def IntroduceDomain(domid, page, port, path):
-    return xshandle().introduce_domain(domid, page, port, path)
+def IntroduceDomain(domid, page, port):
+    return xshandle().introduce_domain(domid, page, port)
 
 def GetDomainPath(domid):
     return xshandle().get_domain_path(domid)
index 3fbad0728df9b91f3e05c8c03091ed57694de091..a66f7d8a4869985c0f2b312d0d4a77e5d83235ef 100644 (file)
@@ -51,7 +51,7 @@
 #include "xenctrl.h"
 #include "tdb.h"
 
-int event_fd;
+extern int eventchn_fd; /* in xenstored_domain.c */
 
 static bool verbose;
 LIST_HEAD(connections);
@@ -319,9 +319,9 @@ static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
        FD_SET(ro_sock, inset);
        if (ro_sock > max)
                max = ro_sock;
-       FD_SET(event_fd, inset);
-       if (event_fd > max)
-               max = event_fd;
+       FD_SET(eventchn_fd, inset);
+       if (eventchn_fd > max)
+               max = eventchn_fd;
        list_for_each_entry(i, &connections, list) {
                if (i->domain)
                        continue;
@@ -1416,15 +1416,37 @@ static void daemonize(void)
 }
 
 
+static void usage(void)
+{
+       fprintf(stderr,
+"Usage:\n"
+"\n"
+"  xenstored <options>\n"
+"\n"
+"where options may include:\n"
+"\n"
+"  --no-domain-init    to state that xenstored should not initialise dom0,\n"
+"  --pid-file <file>   giving a file for the daemon's pid to be written,\n"
+"  --help              to output this message,\n"
+"  --no-fork           to request that the daemon does not fork,\n"
+"  --output-pid        to request that the pid of the daemon is output,\n"
+"  --trace-file <file> giving the file for logging, and\n"
+"  --verbose           to request verbose execution.\n");
+}
+
+
 static struct option options[] = {
        { "no-domain-init", 0, NULL, 'D' },
        { "pid-file", 1, NULL, 'F' },
+       { "help", 0, NULL, 'H' },
        { "no-fork", 0, NULL, 'N' },
        { "output-pid", 0, NULL, 'P' },
        { "trace-file", 1, NULL, 'T' },
        { "verbose", 0, NULL, 'V' },
        { NULL, 0, NULL, 0 } };
 
+extern void dump_conn(struct connection *conn); 
+
 int main(int argc, char *argv[])
 {
        int opt, *sock, *ro_sock, max;
@@ -1435,7 +1457,7 @@ int main(int argc, char *argv[])
        bool no_domain_init = false;
        const char *pidfile = NULL;
 
-       while ((opt = getopt_long(argc, argv, "DF:NPT:V", options,
+       while ((opt = getopt_long(argc, argv, "DF:HNPT:V", options,
                                  NULL)) != -1) {
                switch (opt) {
                case 'D':
@@ -1444,6 +1466,9 @@ int main(int argc, char *argv[])
                case 'F':
                        pidfile = optarg;
                        break;
+               case 'H':
+                       usage();
+                       return 0;
                case 'N':
                        dofork = false;
                        break;
@@ -1509,12 +1534,12 @@ int main(int argc, char *argv[])
            || listen(*ro_sock, 1) != 0)
                barf_perror("Could not listen on sockets");
 
-       /* If we're the first, create .perms file for root. */
+       /* Setup the database */
        setup_structure();
 
        /* Listen to hypervisor. */
        if (!no_domain_init)
-               event_fd = domain_init();
+               domain_init();
 
        /* Restore existing connections. */
        restore_existing_connections();
@@ -1555,7 +1580,7 @@ int main(int argc, char *argv[])
                if (FD_ISSET(*ro_sock, &inset))
                        accept_connection(*ro_sock, false);
 
-               if (FD_ISSET(event_fd, &inset))
+               if (FD_ISSET(eventchn_fd, &inset))
                        handle_event();
 
                list_for_each_entry(i, &connections, list) {
index 74558b1ec91dfa96fca73308b703e460eb1efb9d..9ddcf4f72852ab6b45fe867708160094fdbc3ac0 100644 (file)
 #include <xen/linux/evtchn.h>
 
 static int *xc_handle;
-static int eventchn_fd;
 static int virq_port;
 
+int eventchn_fd = -1; 
+
 struct domain
 {
        struct list_head list;
@@ -79,9 +80,11 @@ static LIST_HEAD(domains);
 #ifndef TESTING
 static void evtchn_notify(int port)
 {
+       int rc; 
+
        struct ioctl_evtchn_notify notify;
        notify.port = port;
-       (void)ioctl(event_fd, IOCTL_EVTCHN_NOTIFY, &notify);
+       rc = ioctl(eventchn_fd, IOCTL_EVTCHN_NOTIFY, &notify);
 }
 #else
 extern void evtchn_notify(int port);
@@ -222,14 +225,14 @@ void handle_event(void)
 {
        uint16_t port;
 
-       if (read(event_fd, &port, sizeof(port)) != sizeof(port))
+       if (read(eventchn_fd, &port, sizeof(port)) != sizeof(port))
                barf_perror("Failed to read from event fd");
 
        if (port == virq_port)
                domain_cleanup();
 
 #ifndef TESTING
-       if (write(event_fd, &port, sizeof(port)) != sizeof(port))
+       if (write(eventchn_fd, &port, sizeof(port)) != sizeof(port))
                barf_perror("Failed to write to event fd");
 #endif
 }
@@ -247,18 +250,18 @@ bool domain_can_write(struct connection *conn)
 }
 
 static struct domain *new_domain(void *context, unsigned int domid,
-                                unsigned long mfn, int port,
-                                const char *path)
+                                unsigned long mfn, int port)
 {
        struct domain *domain;
        struct ioctl_evtchn_bind_interdomain bind;
        int rc;
 
+
        domain = talloc(context, struct domain);
        domain->port = 0;
        domain->shutdown = 0;
        domain->domid = domid;
-       domain->path = talloc_strdup(domain, path);
+       domain->path = talloc_asprintf(domain, "/local/domain/%d", domid);
        domain->interface = xc_map_foreign_range(
                *xc_handle, domain->domid,
                getpagesize(), PROT_READ|PROT_WRITE, mfn);
@@ -269,13 +272,13 @@ static struct domain *new_domain(void *context, unsigned int domid,
        talloc_set_destructor(domain, destroy_domain);
 
        /* Tell kernel we're interested in this event. */
-       bind.remote_domain = domid;
-       bind.remote_port   = port;
-       rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
-       if (rc == -1)
-               return NULL;
+        bind.remote_domain = domid;
+        bind.remote_port   = port;
+        rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+        if (rc == -1)
+            return NULL;
+        domain->port = rc;
 
-       domain->port = rc;
        domain->conn = new_connection(writechn, readchn);
        domain->conn->domain = domain;
 
@@ -302,11 +305,10 @@ static struct domain *find_domain_by_domid(unsigned int domid)
 void do_introduce(struct connection *conn, struct buffered_data *in)
 {
        struct domain *domain;
-       char *vec[4];
+       char *vec[3];
        unsigned int domid;
        unsigned long mfn;
        uint16_t port;
-       const char *path;
 
        if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
                send_error(conn, EINVAL);
@@ -321,10 +323,9 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
        domid = atoi(vec[0]);
        mfn = atol(vec[1]);
        port = atoi(vec[2]);
-       path = vec[3];
 
        /* Sanity check args. */
-       if ((port <= 0) || !is_valid_nodename(path)) {
+       if (port <= 0) { 
                send_error(conn, EINVAL);
                return;
        }
@@ -333,7 +334,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
 
        if (domain == NULL) {
                /* Hang domain off "in" until we're finished. */
-               domain = new_domain(in, domid, mfn, port, path);
+               domain = new_domain(in, domid, mfn, port);
                if (!domain) {
                        send_error(conn, errno);
                        return;
@@ -348,8 +349,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
                /* Check that the given details match the ones we have
                   previously recorded. */
                if (port != domain->remote_port ||
-                   mfn != domain->mfn ||
-                   strcmp(path, domain->path) != 0) {
+                   mfn != domain->mfn) {
                        send_error(conn, EINVAL);
                        return;
                }
@@ -440,10 +440,45 @@ void restore_existing_connections(void)
 {
 }
 
+static int dom0_init(void) 
+{ 
+        int rc, fd, port; 
+        unsigned long mfn; 
+        char str[20]; 
+        struct domain *dom0; 
+        
+        fd = open("/proc/xen/xsd_mfn", O_RDONLY); 
+        
+        rc = read(fd, str, sizeof(str)); 
+        str[rc] = '\0'; 
+        mfn = strtoul(str, NULL, 0); 
+        
+        close(fd); 
+        
+        fd = open("/proc/xen/xsd_port", O_RDONLY); 
+        
+        rc = read(fd, str, sizeof(str)); 
+        str[rc] = '\0'; 
+        port = strtoul(str, NULL, 0); 
+        
+        close(fd); 
+        
+        
+        dom0 = new_domain(NULL, 0, mfn, port); 
+        talloc_steal(dom0->conn, dom0); 
+
+        evtchn_notify(dom0->port); 
+
+        return 0; 
+}
+
+
+
 #define EVTCHN_DEV_NAME  "/dev/xen/evtchn"
 #define EVTCHN_DEV_MAJOR 10
 #define EVTCHN_DEV_MINOR 201
 
+
 /* Returns the event channel handle. */
 int domain_init(void)
 {
@@ -484,6 +519,9 @@ int domain_init(void)
        if (eventchn_fd < 0)
                barf_perror("Failed to open evtchn device");
 
+        if (dom0_init() != 0) 
+                barf_perror("Failed to initialize dom0 state"); 
+     
        bind.virq = VIRQ_DOM_EXC;
        rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
        if (rc == -1)
index 18e875e801f30978eae5106938a1523dd651f6ee..22710d5d014f14645518341286780d0c1a5911a4 100644 (file)
@@ -674,12 +674,12 @@ bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
  */
 bool xs_introduce_domain(struct xs_handle *h,
                         unsigned int domid, unsigned long mfn,
-                        unsigned int eventchn, const char *path)
+                        unsigned int eventchn)
 {
        char domid_str[MAX_STRLEN(domid)];
        char mfn_str[MAX_STRLEN(mfn)];
        char eventchn_str[MAX_STRLEN(eventchn)];
-       struct iovec iov[4];
+       struct iovec iov[3];
 
        sprintf(domid_str, "%u", domid);
        sprintf(mfn_str, "%lu", mfn);
@@ -691,8 +691,6 @@ bool xs_introduce_domain(struct xs_handle *h,
        iov[1].iov_len = strlen(mfn_str) + 1;
        iov[2].iov_base = eventchn_str;
        iov[2].iov_len = strlen(eventchn_str) + 1;
-       iov[3].iov_base = (char *)path;
-       iov[3].iov_len = strlen(path) + 1;
 
        return xs_bool(xs_talkv(h, NULL, XS_INTRODUCE, iov,
                                ARRAY_SIZE(iov), NULL));
index 92007458d39920ef7fcbb13cae0e9a700c7cd158..618e6615a615490931c5d3b5b77127e3738d15cc 100644 (file)
@@ -130,9 +130,7 @@ bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
 bool xs_introduce_domain(struct xs_handle *h,
                         unsigned int domid,
                         unsigned long mfn,
-                         unsigned int eventchn,
-                        const char *path);
-
+                         unsigned int eventchn); 
 /* Release a domain.
  * Tells the store domain to release the memory page to the domain.
  */